package com.warmheart.core.combine.oper;

import java.util.Iterator;
import java.util.Map;

import com.warmheart.core.co.builder.CoBuilder;
import com.warmheart.core.co.oper.Co;
import com.warmheart.core.combine.enums.JoinLinkTypeEnum;
import com.warmheart.core.combine.enums.JoinValueTypeEnum;
import com.warmheart.core.combine.model.JoinInfoModel;
import com.warmheart.core.combine.model.OnModel;
import com.warmheart.core.constant.Globals;
import com.warmheart.core.cors.builder.CoRsBuilder;

/**
 * 
 * @ClassName: On
 * @Description: 该类用作对联合查询条件进行处理
 * @author ZhangJianyang
 * @date 2025-06-16 09:37:02
 *
 * @param <P>
 * @param <PE>
 */
public class On<T extends CoRsBuilder<E, ?>, E extends CoBuilder<T>, P extends CoRsBuilder<PE, ?>, PE extends CoBuilder<P>, J extends CoRsBuilder<JE, ?>, JE extends CoBuilder<J>> {

    private final Join<T, E> join;

    private final Co<P, PE> pCo;

    private final Co<J, JE> jCo;

    public On(Join<T, E> join, Co<P, PE> pCo, Co<J, JE> jCo) {
        this.join = join;
        this.pCo = pCo;
        this.jCo = jCo;
    }

    public Join<T, E> eq(JoinLinkTypeEnum... args) {
        JoinLinkTypeEnum joinLinkTypeEnum = null;
        if (args.length > 0) {
            joinLinkTypeEnum = args[0];
        } else {
            joinLinkTypeEnum = JoinLinkTypeEnum.AND;
        }
        Map<String, JoinInfoModel> joinMap = this.join.fetchMain().getJoinModel().getJoinMap();
        if (joinMap.get(this.join.fetchJoinAlias()).getOnList().size() == 0) {
            joinLinkTypeEnum = JoinLinkTypeEnum.ON;
        }
        String pAlias = this.join.fetchCombineModel().getJoinAliasMap().get(this.pCo.core());
        String jAlias = this.join.fetchCombineModel().getJoinAliasMap().get(this.jCo.core());
        joinMap.get(this.join.fetchJoinAlias())
                .getOnList()
                .add(new OnModel(pAlias + Globals.DOT + this.pCo.fetchField(), "=", JoinValueTypeEnum.COLUMN, jAlias
                        + Globals.DOT + this.jCo.fetchField(), null, this.pCo.checkDate(), this.pCo.fetchFormat(),
                        joinLinkTypeEnum, null));
        return this.join;
    }

    public Join<T, E> notEq(JoinLinkTypeEnum... args) {
        JoinLinkTypeEnum joinLinkTypeEnum = null;
        if (args.length > 0) {
            joinLinkTypeEnum = args[0];
        } else {
            joinLinkTypeEnum = JoinLinkTypeEnum.AND;
        }
        Map<String, JoinInfoModel> joinMap = this.join.fetchMain().getJoinModel().getJoinMap();
        if (joinMap.get(this.join.fetchJoinAlias()).getOnList().size() == 0) {
            joinLinkTypeEnum = JoinLinkTypeEnum.ON;
        }
        String pAlias = this.join.fetchCombineModel().getJoinAliasMap().get(this.pCo.core());
        String jAlias = this.join.fetchCombineModel().getJoinAliasMap().get(this.jCo.core());
        joinMap.get(this.join.fetchJoinAlias())
                .getOnList()
                .add(new OnModel(pAlias + Globals.DOT + this.pCo.fetchField(), "!=", JoinValueTypeEnum.COLUMN, jAlias
                        + Globals.DOT + this.jCo.fetchField(), null, this.pCo.checkDate(), this.pCo.fetchFormat(),
                        joinLinkTypeEnum, null));
        return this.join;
    }

    public Join<T, E> lt(JoinLinkTypeEnum... args) {
        JoinLinkTypeEnum joinLinkTypeEnum = null;
        if (args.length > 0) {
            joinLinkTypeEnum = args[0];
        } else {
            joinLinkTypeEnum = JoinLinkTypeEnum.AND;
        }
        Map<String, JoinInfoModel> joinMap = this.join.fetchMain().getJoinModel().getJoinMap();
        if (joinMap.get(this.join.fetchJoinAlias()).getOnList().size() == 0) {
            joinLinkTypeEnum = JoinLinkTypeEnum.ON;
        }
        String pAlias = this.join.fetchCombineModel().getJoinAliasMap().get(this.pCo.core());
        String jAlias = this.join.fetchCombineModel().getJoinAliasMap().get(this.jCo.core());
        joinMap.get(this.join.fetchJoinAlias())
                .getOnList()
                .add(new OnModel(pAlias + Globals.DOT + this.pCo.fetchField(), "<", JoinValueTypeEnum.COLUMN, jAlias
                        + Globals.DOT + this.jCo.fetchField(), null, this.pCo.checkDate(), this.pCo.fetchFormat(),
                        joinLinkTypeEnum, null));
        return this.join;
    }

    public Join<T, E> lte(JoinLinkTypeEnum... args) {
        JoinLinkTypeEnum joinLinkTypeEnum = null;
        if (args.length > 0) {
            joinLinkTypeEnum = args[0];
        } else {
            joinLinkTypeEnum = JoinLinkTypeEnum.AND;
        }
        Map<String, JoinInfoModel> joinMap = this.join.fetchMain().getJoinModel().getJoinMap();
        if (joinMap.get(this.join.fetchJoinAlias()).getOnList().size() == 0) {
            joinLinkTypeEnum = JoinLinkTypeEnum.ON;
        }
        String pAlias = this.join.fetchCombineModel().getJoinAliasMap().get(this.pCo.core());
        String jAlias = this.join.fetchCombineModel().getJoinAliasMap().get(this.jCo.core());
        joinMap.get(this.join.fetchJoinAlias())
                .getOnList()
                .add(new OnModel(pAlias + Globals.DOT + this.pCo.fetchField(), "<=", JoinValueTypeEnum.COLUMN, jAlias
                        + Globals.DOT + this.jCo.fetchField(), null, this.pCo.checkDate(), this.pCo.fetchFormat(),
                        joinLinkTypeEnum, null));
        return this.join;
    }

    public Join<T, E> gt(JoinLinkTypeEnum... args) {
        JoinLinkTypeEnum joinLinkTypeEnum = null;
        if (args.length > 0) {
            joinLinkTypeEnum = args[0];
        } else {
            joinLinkTypeEnum = JoinLinkTypeEnum.AND;
        }
        Map<String, JoinInfoModel> joinMap = this.join.fetchMain().getJoinModel().getJoinMap();
        if (joinMap.get(this.join.fetchJoinAlias()).getOnList().size() == 0) {
            joinLinkTypeEnum = JoinLinkTypeEnum.ON;
        }
        String pAlias = this.join.fetchCombineModel().getJoinAliasMap().get(this.pCo.core());
        String jAlias = this.join.fetchCombineModel().getJoinAliasMap().get(this.jCo.core());
        joinMap.get(this.join.fetchJoinAlias())
                .getOnList()
                .add(new OnModel(pAlias + Globals.DOT + this.pCo.fetchField(), ">", JoinValueTypeEnum.COLUMN, jAlias
                        + Globals.DOT + this.jCo.fetchField(), null, this.pCo.checkDate(), this.pCo.fetchFormat(),
                        joinLinkTypeEnum, null));
        return this.join;
    }

    public Join<T, E> gte(JoinLinkTypeEnum... args) {
        JoinLinkTypeEnum joinLinkTypeEnum = null;
        if (args.length > 0) {
            joinLinkTypeEnum = args[0];
        } else {
            joinLinkTypeEnum = JoinLinkTypeEnum.AND;
        }
        Map<String, JoinInfoModel> joinMap = this.join.fetchMain().getJoinModel().getJoinMap();
        if (joinMap.get(this.join.fetchJoinAlias()).getOnList().size() == 0) {
            joinLinkTypeEnum = JoinLinkTypeEnum.ON;
        }
        String pAlias = this.join.fetchCombineModel().getJoinAliasMap().get(this.pCo.core());
        String jAlias = this.join.fetchCombineModel().getJoinAliasMap().get(this.jCo.core());
        joinMap.get(this.join.fetchJoinAlias())
                .getOnList()
                .add(new OnModel(pAlias + Globals.DOT + this.pCo.fetchField(), ">=", JoinValueTypeEnum.COLUMN, jAlias
                        + Globals.DOT + this.jCo.fetchField(), null, this.pCo.checkDate(), this.pCo.fetchFormat(),
                        joinLinkTypeEnum, null));
        return this.join;
    }

    public Join<T, E> preLike(JoinLinkTypeEnum... args) {
        JoinLinkTypeEnum joinLinkTypeEnum = null;
        if (args.length > 0) {
            joinLinkTypeEnum = args[0];
        } else {
            joinLinkTypeEnum = JoinLinkTypeEnum.AND;
        }
        Map<String, JoinInfoModel> joinMap = this.join.fetchMain().getJoinModel().getJoinMap();
        if (joinMap.get(this.join.fetchJoinAlias()).getOnList().size() == 0) {
            joinLinkTypeEnum = JoinLinkTypeEnum.ON;
        }
        String pAlias = this.join.fetchCombineModel().getJoinAliasMap().get(this.pCo.core());
        String jAlias = this.join.fetchCombineModel().getJoinAliasMap().get(this.jCo.core());
        joinMap.get(this.join.fetchJoinAlias())
                .getOnList()
                .add(new OnModel(pAlias + Globals.DOT + this.pCo.fetchField(), "like", JoinValueTypeEnum.COLUMN, jAlias
                        + Globals.DOT + this.jCo.fetchField(), null, this.pCo.checkDate(), this.pCo.fetchFormat(),
                        joinLinkTypeEnum, "pre"));
        return this.join;
    }

    public Join<T, E> sufLike(JoinLinkTypeEnum... args) {
        JoinLinkTypeEnum joinLinkTypeEnum = null;
        if (args.length > 0) {
            joinLinkTypeEnum = args[0];
        } else {
            joinLinkTypeEnum = JoinLinkTypeEnum.AND;
        }
        Map<String, JoinInfoModel> joinMap = this.join.fetchMain().getJoinModel().getJoinMap();
        if (joinMap.get(this.join.fetchJoinAlias()).getOnList().size() == 0) {
            joinLinkTypeEnum = JoinLinkTypeEnum.ON;
        }
        String pAlias = this.join.fetchCombineModel().getJoinAliasMap().get(this.pCo.core());
        String jAlias = this.join.fetchCombineModel().getJoinAliasMap().get(this.jCo.core());
        joinMap.get(this.join.fetchJoinAlias())
                .getOnList()
                .add(new OnModel(pAlias + Globals.DOT + this.pCo.fetchField(), "like", JoinValueTypeEnum.COLUMN, jAlias
                        + Globals.DOT + this.jCo.fetchField(), null, this.pCo.checkDate(), this.pCo.fetchFormat(),
                        joinLinkTypeEnum, "suf"));
        return this.join;
    }

    public Join<T, E> bothLike(JoinLinkTypeEnum... args) {
        JoinLinkTypeEnum joinLinkTypeEnum = null;
        if (args.length > 0) {
            joinLinkTypeEnum = args[0];
        } else {
            joinLinkTypeEnum = JoinLinkTypeEnum.AND;
        }
        Map<String, JoinInfoModel> joinMap = this.join.fetchMain().getJoinModel().getJoinMap();
        if (joinMap.get(this.join.fetchJoinAlias()).getOnList().size() == 0) {
            joinLinkTypeEnum = JoinLinkTypeEnum.ON;
        }
        String pAlias = this.join.fetchCombineModel().getJoinAliasMap().get(this.pCo.core());
        String jAlias = this.join.fetchCombineModel().getJoinAliasMap().get(this.jCo.core());
        joinMap.get(this.join.fetchJoinAlias())
                .getOnList()
                .add(new OnModel(pAlias + Globals.DOT + this.pCo.fetchField(), "like", JoinValueTypeEnum.COLUMN, jAlias
                        + Globals.DOT + this.jCo.fetchField(), null, this.pCo.checkDate(), this.pCo.fetchFormat(),
                        joinLinkTypeEnum, "both"));
        return this.join;
    }

    public void clear() {
        String pAlias = this.join.fetchCombineModel().getJoinAliasMap().get(this.pCo.core());
        String jAlias = this.join.fetchCombineModel().getJoinAliasMap().get(this.jCo.core());
        Iterator<OnModel> onIterator = this.join.fetchMain().getJoinModel().getJoinMap()
                .get(this.join.fetchJoinAlias()).getOnList().iterator();
        while (onIterator.hasNext()) {
            OnModel element = onIterator.next();
            if ((pAlias + Globals.DOT + this.pCo.fetchField()).equals(element.getFieldName())
                    && (jAlias + Globals.DOT + this.jCo.fetchField()).equals(element.getJoinFieldName())) {
                onIterator.remove();
            }
        }
    }

    public Join<T, E> join() {
        return this.join;
    }
}
